package com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.state.data;

import com.clp.protocol.iec104.iec104.apdu.asdu.Cot;
import com.clp.protocol.iec104.iec104.apdu.asdu.IAsdu;
import com.clp.protocol.iec104.iec104.apdu.asdu.infoobj.InfoObj;
import com.clp.protocol.iec104.iec104.apdu.asdu.infoobj.infoelem.C_SC_NA_1_InfoElem;
import com.clp.protocol.iec104.iec104.definition.Tc;
import com.clp.protocol.iec104.iec104.definition.TypeTag;
import com.clp.protocol.iec104.iec104.definition.cot.Cause;
import com.clp.protocol.iec104.iec104.definition.cot.Pn;
import com.clp.protocol.iec104.iec104.server.slave.SlaveDataConfig;
import com.clp.protocol.iec104.iec104.server.slavechannel.pipeline.PipelineManager;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class TcDataStateHandler extends AbstractDataStateHandler {

    private enum State {
        R_SELECT,
        S_SELECT_ACK_YES,
        S_SELECT_ACK_NO,
        R_EXECUTE,
        S_EXECUTE_ACK_YES,
        S_EXECUTE_ACK_NO,
        S_FINISHED
    }

    private static class PtState {
        private final int addr;
        private volatile State state;

        public PtState(int addr) {
            this.addr = addr;
            reset();
        }

        public void reset() {
            state = State.S_FINISHED;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            PtState ptState = (PtState) o;
            return addr == ptState.addr;
        }

        @Override
        public int hashCode() {
            return Objects.hash(addr);
        }
    }

    private final TcDataReactor dataReactor;
    private final Map<Integer, PtState> ptStateMap = new HashMap<>(128);

    public TcDataStateHandler(PipelineManager manager, SlaveDataConfig dataConfig) {
        super(manager);
        this.dataReactor = dataConfig.getTcDataReactor();
    }

    @Override
    protected void resetState() {
        ptStateMap.forEach((addr, ptState) -> ptState.reset());
    }

    @Override
    protected void afterResetState() {

    }

    @Override
    protected IAsdu updateStateByRecv(IAsdu iAsdu) throws Exception {
        TcDataReactor.TcType tcType = dataReactor.getTcType();
        TypeTag tcTypeTag = tcType.getTypeTag();

        TypeTag typeTag = iAsdu.getTypeTag();
        Cot cot = iAsdu.getCot();
        Pn pn = cot.getPn();
        Cause cause = cot.getCause();

        if (typeTag == TypeTag.C_SC_NA_1) { // 单点遥控
            InfoObj infoObj = iAsdu.getInfoObjs().get(0);
            C_SC_NA_1_InfoElem infoElem = infoObj.getInfoElem().castTo(C_SC_NA_1_InfoElem.class);
            Tc.CmdType cmdType = infoElem.getCmdType();
            Tc.OnePointSwitch pointSwitch = infoElem.getOnePointSwitch();

            if (cmdType == Tc.CmdType.SELECT) { // 选择

            } else if (cmdType == Tc.CmdType.EXECUTE) { // 执行

            }

            if (typeTag != tcTypeTag) { // 不支持的遥控类型

            } else { // 支持该类型

            }
        } else if (typeTag == TypeTag.C_DC_NA_1) { // 双点遥控
            if (typeTag != tcTypeTag) { // 不支持的遥控类型

            } else { // 支持该类型

            }
        }

        return iAsdu;
    }

    @Override
    protected IAsdu updateStateBySend(IAsdu iAsdu) throws Exception {
        return null;
    }

    @Nullable
    @Override
    protected ScheduledTask getScheduledTask() {
        return null;
    }
}
